/**
* @file    hal_screen_OTA7290B.c
* @brief   hal screen implemention
*
* Copyright (c) 2017 Huawei Tech.Co.,Ltd
*
* @author    HiMobileCam Reference Develop Team
* @date      2017/12/12
* @version   1.0

*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include "stdlib.h"
#include <sys/ioctl.h>

#include "hi_appcomm_util.h"
#include "hi_hal_common.h"
#include "hi_hal_screen.h"
#include "hi_hal_screen_inner.h"
#include "hi_hal_gpio_inner.h"

#include "hi_mipi_tx.h"

#if (defined(AMP_LINUX_HUAWEILITE) && defined(__HuaweiLite__)) || !(defined(AMP_LINUX_HUAWEILITE))
#include "screen_mipidsi.h"
#endif

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

/** \addtogroup     SCREEN */
/** @{ */  /** <!-- [SCREEN] */

/**when in linux and liteos version, the branch is in Liteos end*/
/**Single Linux os Single Liteos*/
#if (defined(AMP_LINUX_HUAWEILITE) && defined(__HuaweiLite__)) || !(defined(AMP_LINUX_HUAWEILITE))

typedef struct tagHAL_SCREEN_Ota7290bCtx
{
    HI_HAL_SCREEN_STATE_E screenDisplayState;
} HAL_SCREEN_Ota7290bCtx;
static HAL_SCREEN_Ota7290bCtx g_halScreenOta7290bCtx = {HI_HAL_SCREEN_STATE_BUIT};

/**MIPI Screen do reset in HAL, RGB do reset in DRV*/
static HI_VOID HAL_SCREEN_Reset(HI_VOID)
{
#if defined(HI3559V200)
     /**GPIO0_5*/
    HI_U32 setValue = 0x1 << 5;
    HI_U32 mask = 0x1 << 5;

    /**Set direction*/
    writereg(setValue, mask, 0x120D0400);
    himm(0x120D0080,0x20);
    himm(0x120D0080,0x00);
    himm(0x120D0080,0x20);
#endif
}

/**Use GPIO high_low level must be set GPIO pin reuse*/
/**Use PWM. must set Pin reuse and PWM config*/
static HI_VOID HAL_SCREEN_LumaInit(HI_VOID)
{
#if (defined(BOARD_DASHCAM_REFB) && defined(HI3559V200))
    HI_U32 value = 0;
    MLOGD("init screen_pwm\n");
    /* set GPIO6_7 ---> PWM1 */
    himd(0x111f0028, &value);
    value |= 0x1;
    himm(0x111f0028,value);

    /* set PWM clock */
    himd(0x120101bc, &value);
    value &= ~(0x11 << 8);   /* [9:8]--> 00 :3MHz */
    himm(0x120101bc, value);

    himd(0x120101bc, &value);
    value |= 0x1 << 7 ;      /* open PWM clock enable */
    himm(0x120101bc, value);

    /*set PWM1 */
    himm(0x1207002c, 0x4);   /* close PWM1 enable*/
    himm(0x12070020, 0x3e8); /* cycle 1K --> frequency 3KHz */
    himm(0x12070024, 0x3e8); /* default duty cycle is 100*/
    himm(0x1207002c, 0x5);   /* open PWM1 enable*/
#endif
}

static HI_VOID HAL_SCREEN_MipiCmd(HI_VOID)
{
}


static HI_S32 HAL_SCREEN_OTA7290B_Init(HI_VOID)
{
    HI_S32 ret = HI_SUCCESS;
    ret = MIPIDSI_Init();
    if (ret != HI_SUCCESS) {
        MLOGE("MIPIDSI_Init failed.\n");
        return HI_HAL_EINTER;
    }
    HAL_SCREEN_Reset();
    HAL_SCREEN_LumaInit();
    combo_dev_cfg_t mipiDevCfg =
    {
        .devno = 0,
        .lane_id = {0, 1, 2, 3},
        .output_mode = OUTPUT_MODE_DSI_VIDEO,
        .output_format = OUT_FORMAT_RGB_24_BIT,
        .video_mode =  BURST_MODE,
        .sync_info = {
            .vid_pkt_size     = 400,
            .vid_hsa_pixels   = 22,
            .vid_hbp_pixels   = 38,
            .vid_hline_pixels = 470,
            .vid_vsa_lines    = 20,
            .vid_vbp_lines    = 30,
            .vid_vfp_lines    = 30,
            .vid_active_lines = 1600,
            .edpi_cmd_size = 0,
        },
        .phy_data_rate = 1000,
        .pixel_clk = 40623,
    };
    ret = MIPIDSI_SetDeviceConfig(&mipiDevCfg);
    if (ret != HI_SUCCESS) {
        MLOGE("MIPIDSI_SetDeviceConfig failed.\n");
        return HI_HAL_EINTER;
    }

    HAL_SCREEN_MipiCmd();
    ret = MIPIDSI_EnableVideoDataTransport();
    if (ret != HI_SUCCESS) {
        MLOGE("MIPIDSI_EnableVideoDataTransport failed.\n");
        return HI_HAL_EINTER;
    }
    g_halScreenOta7290bCtx.screenDisplayState = HI_TRUE;
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetAttr(HI_HAL_SCREEN_ATTR_S* pstAttr)
{
    HI_APPCOMM_CHECK_POINTER(pstAttr, HI_HAL_EINVAL);
    pstAttr->enType = HI_HAL_SCREEN_INTF_TYPE_MIPI;

/**Just For use a certain screen to Show a diffirent resolution VO*/
/**For example, scrren is 1600*400, but vo frame is 1280*320,*/
#ifdef CFG_LCD_UISRC_DEST_HEIGHT
    pstAttr->stAttr.u32Width = CFG_LCD_UISRC_DEST_HEIGHT;
#else
    pstAttr->stAttr.u32Width = 400;
#endif

#ifdef CFG_LCD_UISRC_DEST_WIDTH
    pstAttr->stAttr.u32Height = CFG_LCD_UISRC_DEST_WIDTH;
#else
    pstAttr->stAttr.u32Height = 1600;
#endif

    pstAttr->stAttr.u32Framerate = 60;
    pstAttr->stAttr.stClkAttr.u32DevDiv = 1;
    pstAttr->stAttr.stClkAttr.bClkReverse = HI_TRUE;
    pstAttr->stAttr.stClkAttr.enClkType = HI_HAL_SCREEN_CLK_TYPE_PLL;
    pstAttr->stAttr.stClkAttr.stClkPll.u32Fbdiv = 71;
    pstAttr->stAttr.stClkAttr.stClkPll.u32Frac = 0;
    pstAttr->stAttr.stClkAttr.stClkPll.u32Refdiv = 2;
    pstAttr->stAttr.stClkAttr.stClkPll.u32Postdiv1 = 4;
    pstAttr->stAttr.stClkAttr.stClkPll.u32Postdiv2 = 4;

    pstAttr->stAttr.stSynAttr.u16Vact = 1600;
    pstAttr->stAttr.stSynAttr.u16Vbb = 50;
    pstAttr->stAttr.stSynAttr.u16Vfb = 30;
    pstAttr->stAttr.stSynAttr.u16Hact = 400;
    pstAttr->stAttr.stSynAttr.u16Hbb = 80;
    pstAttr->stAttr.stSynAttr.u16Hfb = 50;
    pstAttr->stAttr.stSynAttr.u16Hpw = 30;
    pstAttr->stAttr.stSynAttr.u16Vpw = 20;
    pstAttr->stAttr.stSynAttr.bIdv = 0;
    pstAttr->stAttr.stSynAttr.bIhs = 0;
    pstAttr->stAttr.stSynAttr.bIvs = 0;
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetDisplayState(HI_HAL_SCREEN_STATE_E* penDisplayState)
{
    HI_APPCOMM_CHECK_POINTER(penDisplayState, HI_HAL_EINVAL);
    *penDisplayState = g_halScreenOta7290bCtx.screenDisplayState;
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetDisplayState(HI_HAL_SCREEN_STATE_E enDisplayState)
{
    g_halScreenOta7290bCtx.screenDisplayState = enDisplayState;
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetLuma(HI_U32* pu32Luma)
{
    HI_APPCOMM_CHECK_POINTER(pu32Luma, HI_HAL_EINVAL);
#if ((defined(HI3559V200))&&(defined(BOARD_DASHCAM_REFB)))
    HI_U32 value = 0;
    himd(0x12070024, &value);
    *pu32Luma = value * 100 / 1000;
#endif
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetLuma(HI_U32 u32Luma)
{
#if ((defined(HI3559V200))&&(defined(BOARD_DASHCAM_REFB)))
    HI_U32 value = 0;
    if (u32Luma == 0) {
        u32Luma = 1;
    }
    value = u32Luma * 1000 / 100; /* conversion luma_value */
    himm(0x1207002c, 0x4);        /* close PWM1 enable*/
    himm(0x12070024, value);      /* set duty cycle */
    himm(0x1207002c, 0x5);        /* open PWM1 enable*/
#endif
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetSatuature(HI_U32* pu32Satuature)
{
    HI_APPCOMM_CHECK_POINTER(pu32Satuature, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetSatuature(HI_U32 u32Satuature)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetContrast(HI_U32* pu32Contrast)
{
    HI_APPCOMM_CHECK_POINTER(pu32Contrast, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetContrast(HI_U32 u32Contrast)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetBackLightState(HI_HAL_SCREEN_STATE_E enBackLightState)
{

#if defined(HI3559V200)

#ifndef BOARD_DASHCAM_REFB
    /**Set GPIO*/

    HI_U32 setValue = 0x1 << 7;
    HI_U32 mask = 0x1 << 7;

    writereg(setValue, mask, 0x120D6400);

    if (enBackLightState == HI_HAL_SCREEN_STATE_OFF) {
        himm(0x120D6200, 0x0);
    } else if (enBackLightState == HI_HAL_SCREEN_STATE_ON) {
        himm(0x120D6200,0x80);
    }
#else
    /**Set PWM*/
    if (enBackLightState == HI_HAL_SCREEN_STATE_OFF) {
        himm(0x1207002c, 0x4); /* close PWM1 enable*/
    } else if (enBackLightState == HI_HAL_SCREEN_STATE_ON) {
        himm(0x1207002c, 0x5); /* open PWM1 enable */
    }
#endif

#endif
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetBackLightState(HI_HAL_SCREEN_STATE_E* penBackLightState)
{
    HI_APPCOMM_CHECK_POINTER(penBackLightState, HI_HAL_EINVAL);
#if ((defined(HI3559V200))&&(defined(BOARD_DASHCAM_REFB)))

#ifndef BOARD_DASHCAM_REFB
    HI_U32 value = 0;
    himd(0x120D6200,&value);
    if(value & 0x80) {
        *penBackLightState = HI_HAL_SCREEN_STATE_ON;
    } else {
        *penBackLightState = HI_HAL_SCREEN_STATE_OFF;
    }
#else
    HI_U32 value = 0;
    himd(0x1207002c,&value);
    if(value & 0x1) {
        *penBackLightState = HI_HAL_SCREEN_STATE_ON;
    } else {
        *penBackLightState = HI_HAL_SCREEN_STATE_OFF;
    }
#endif

#endif
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_Deinit(HI_VOID)
{
    MIPIDSI_Deinit();
    return HI_SUCCESS;
}

#else

static HI_S32 HAL_SCREEN_OTA7290B_Init(HI_VOID)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetAttr(HI_HAL_SCREEN_ATTR_S* pstAttr)
{

    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetDisplayState(HI_HAL_SCREEN_STATE_E* penDisplayState)
{
    HI_APPCOMM_CHECK_POINTER(penDisplayState, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetDisplayState(HI_HAL_SCREEN_STATE_E enDisplayState)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetLuma(HI_U32* pu32Luma)
{
    HI_APPCOMM_CHECK_POINTER(pu32Luma, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetLuma(HI_U32 u32Luma)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetSatuature(HI_U32* pu32Satuature)
{
    HI_APPCOMM_CHECK_POINTER(pu32Satuature, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetSatuature(HI_U32 u32Satuature)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetContrast(HI_U32* pu32Contrast)
{
    HI_APPCOMM_CHECK_POINTER(pu32Contrast, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetContrast(HI_U32 u32Contrast)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_SetBackLightState(HI_HAL_SCREEN_STATE_E enBackLightState)
{
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_GetBackLightState(HI_HAL_SCREEN_STATE_E* penBackLightState)
{
    HI_APPCOMM_CHECK_POINTER(penBackLightState, HI_HAL_EINVAL);
    return HI_SUCCESS;
}

static HI_S32 HAL_SCREEN_OTA7290B_Deinit(HI_VOID)
{
    return HI_SUCCESS;
}
#endif

HI_HAL_SCREEN_OBJ_S stHALSCREENObj =
{
    .pfnInit = HAL_SCREEN_OTA7290B_Init,
    .pfnGetAttr = HAL_SCREEN_OTA7290B_GetAttr,
    .pfnSetDisplayState = HAL_SCREEN_OTA7290B_SetDisplayState,
    .pfnGetDisplayState = HAL_SCREEN_OTA7290B_GetDisplayState,
    .pfnSetBackLightState = HAL_SCREEN_OTA7290B_SetBackLightState,
    .pfnGetBackLightState = HAL_SCREEN_OTA7290B_GetBackLightState,
    .pfnSetLuma = HAL_SCREEN_OTA7290B_SetLuma,
    .pfnGetLuma = HAL_SCREEN_OTA7290B_GetLuma,
    .pfnSetSaturature = HAL_SCREEN_OTA7290B_SetSatuature,
    .pfnGetSaturature = HAL_SCREEN_OTA7290B_GetSatuature,
    .pfnSetContrast = HAL_SCREEN_OTA7290B_SetContrast,
    .pfnGetContrast = HAL_SCREEN_OTA7290B_GetContrast,
    .pfnDeinit = HAL_SCREEN_OTA7290B_Deinit,
};

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

